<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 总结:
        // 浅拷贝：仅仅是指向被复制的内存地址，如果原地址发生改变，那么浅复制出来的对象也会相应的改变。特点:只复制一层 。
        // 方法有： Object.assign(), es6中的展开运行符{...a,...b} var in 遍历对象，进行单层赋值
        // 深拷贝：在计算机中开辟一块新的内存地址用于存放复制的对象。特点:可复制多层 。
        // 方法有 JSON.parse(JSON.stringify(obj))  ，递归深拷贝：如果对象里还有对象，也就是多层？先判断是不
        // 是对象,是的话递归循环遍历赋值



        // 值类型（基本类型）：字符串（string）、数值（number）、布尔值（boolean）、undefined、null ；
        // 引用类型：对象（Object）、数组（Array）、函数（Function）；
        // 浅拷贝是创建一个新对象，这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型，拷贝的就是基本类型的值，如果属性是引用类型，拷贝的就是内存地址 。
        // 深拷贝是将一个对象从内存中完整的拷贝一份出来, 从堆内存中开辟一个新的区域存放新对象。
        // 区别：浅拷贝基本类型之前互不影响，引用类型其中一个对象改变了地址，就会影响另一个对象；深拷贝
        // 改变新对象不会影响原对象，他们之前互不影响。
        // 赋值
        //对象赋值
        // let obj1 = {
        //     name: '张三', action: { say: 'hi' };
        //     let obj2 = obj1;
        //     obj2.name = '李四';
        //     obj2.action.say = 'hello'
        //     console.log('obj1', obj1)
        //     // obj1 { name: '李四', action: { say: 'hello'}
        //     console.log('obj2', obj2)
        //     // obj2 { name: '李四', action: { say: 'hello'}

        // 浅拷贝
        // Object.assign()
        //浅拷贝
        // let obj1 = {
        //     name: '张三', action: { say: 'hi' };
        //     let obj2 = Object.assign({}, obj1);
        //     obj2.name = '李四';
        //     obj2.action.say = 'hello'
        //     console.log('obj1', obj1)
        //     // obj1 { name: '张三', action: { say: 'hello'}
        //     console.log('obj2', obj2)
        //     // obj2 { name: '李四', action: { say: 'hello'}
        // 展开运算符…
        // 展开运算符是一个 es6特性，它提供了一种非常方便的方式来执行浅拷贝，这与 Object.assign()的功能相同。
        // concat()，slice()也属于浅拷贝

        //   深拷贝
        // JSON.parse(JSON.stringify())
        //深拷贝
        // let obj1 = {
        //     name: '张三', action: { say: 'hi' };
        //     let obj2 = JSON.parse(JSON.stringify(obj1));
        //     obj2.name = '李四';
        //     obj2.action.say = 'hello'
        //  console.log('obj1', obj1)
        //  // obj1 { name: '张三', action: { say: 'hi'}
        //  console.log('obj2', obj2)
        //  // obj2 { name: '李四', action: { say: 'hello'}

        
        // jQuery.extend()
        // $.extend(deepCopy, target, object1, [objectN])//第一个参数为true,就是深拷贝
        //深拷贝
        // let obj1 = {
        //     name: '张三', action: { say: 'hi' };
        //     let obj2 = $.extend(true, {}, obj1);
        //     obj2.name = '李四';
        //     obj2.action.say = 'hello'
        // console.log('obj1', obj1)
        // // obj1 { name: '张三', action: { say: 'hi'}
        // console.log('obj2', obj2)
        // // obj2 { name: '李四', action: { say: 'hello'}

        //输出结果,为什么?
        // var obj4 = { a: 1, b: 2, c: 3, d: { e: 4 } }
        // //  var obj5=obj4  // 2,2,3,5 因为是对象,它属于浅拷贝赋值
        // //  var obj5= JSON.parse(JSON.stringify(obj4))  //深拷贝  1,2,3,4
        // var obj5 = { ...obj4 } //展开运算符并不是深拷贝，而是浅拷贝。为什么a的值不变？因为a是基本类型,基本类型不会被拷贝，而是直接赋值。1,2,3,5
        // obj4.a = 2
        // obj4.d.e = 5
        // console.log(obj4, obj5); //2235,1235


        // //基本类型：数字、字符串、布尔值、null、undefined
        // var a = 10;
        // var b = a;
        // b = 20;
        // console.log(a, b); // 10,20  基本类型存储在栈中，每声明一个变量，就会分配一块内存存储该值

        // // //引用类型：对象{}、数组
        // var c = [1, 2];
        // var d = c;
        // d[0] = 3;
        // console.log(c, d); // [3,2] [3,2]  引用类型存储在堆中，在内存中这两个变量指向的是同一个地址，所以改变一个另一个也会改变。

        // //用深拷贝方法-不能改变原数据
        // var e = [1, 2];
        // var f = JSON.parse(JSON.stringify(e)); //深拷贝方法
        // e[0] = 3;
        // console.log(211, e, f);

        // 深拷贝其它方法 JSON.parse(JSON.stringify(obj))  缺点：不能复制RegExp、Error，undefined,日期对象等



        //对象有无穷无尽，不知道多少层？ 用递归遍历
        // let obj1 = {
        //     a: 1,
        //     b: {
        //         // b1:[1],
        //         b2: {
        //             c1: 33
        //         },
        //         b3: 1
        //     }
        // }

        // let obj2 = {
        //     a: 2,
        //     b: {

        //         // b1:[2],
        //         b2: {
        //             c2: 44
        //         },
        //         b3: 2
        //     }
        // }
        // //通过简单的递归-如果有数组有bug
        // function deep1(obj1, obj2) {
        //     for (const key in obj2) {
        //         //如果是多层，层层遍历对象的对象
        //         if (obj2[key] instanceof Object) {
        //             // for (const key1 in obj2[key]) {
        //             //     obj1[key][key1]=obj2[key][key1]
        //             // }
        //             //递归调用
        //             deep1(obj1[key], obj2[key])
        //         }
        //         //除非1层
        //         else {
        //             obj1[key] = obj2[key]
        //         }

        //     }
        //     return obj1
        // }
        // console.log(158, deep1(obj1, obj2));


    </script>
</body>

</html>